package com.falcon.mvc.aop;

import com.alibaba.fastjson2.JSONObject;
import com.falcon.mvc.anno.LogRequest;
import com.falcon.mvc.core.RequestAttrHolder;
import com.falcon.mvc.enums.RequestAttrNameEnum;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.Optional;

/** 日志处理: 打印请求参数和响应结果
 * @author zongf
 * @date 2024-02-04
 **/
@Slf4j
@Component
@Aspect
@Order(-1)
public class RequestLogAspect {

    @Autowired
    private RequestAttrHolder requestAttrHolder;

    // 切面: 切 com.falcon.** 所有子包下命名为 xxxController 的 返回值为 BaseResponse 的方法
    @Pointcut("execution(* com.falcon..*Controller.*(..))")
    public void pointCut() {}

    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();

        // 默认拦截 Controller 目录下的所有方法
        boolean logRequest = true;
        boolean logResponse = true;

        LogRequest annotation = methodSignature.getMethod().getAnnotation(LogRequest.class);
        if (Objects.nonNull(annotation)) {
            logRequest = logRequest & Optional.ofNullable(annotation.request()).orElse(true);
            logResponse = logResponse & Optional.ofNullable(annotation.request()).orElse(true);;
        }

        // 存储
        requestAttrHolder.set(RequestAttrNameEnum.LOG_RESPONSE, logRequest);

        // 打印请求日志
        if (logResponse) {
            this.logRequest(methodSignature.getParameterNames(), joinPoint.getArgs());
        }

        // 执行方法
        return joinPoint.proceed();
    }

    private void logRequest(String[] parameterNames, Object[] args) {
        if(args.length == 0) return;

        StringBuffer sb = new StringBuffer();
        try {
            for (int i = 0; i < args.length; i++) {
                String paramStr = Objects.isNull(args[i]) ? null : JSONObject.toJSONString(args[i]);
                sb.append(parameterNames[i]).append("=").append(paramStr).append(", ");
                log.info("参数列表: {}", sb.substring(0, sb.length() - 2));
            }
        } catch (Exception ex) {
            log.warn("参数解析异常:", ex);
        }
    }

}
